import { PlusOutlined, SearchOutlined } from '@ant-design/icons'
import { keywordCompare } from '@gnlab/utils'
import { message, Button, AutoComplete, Input, Tag, Spin } from 'antd'
import type { DefaultOptionType } from 'antd/es/select'
import { EditModal } from '@/desktop/components'
import AddOrChooseTagModal from '@/desktop/views/app-center/group-tags/add-or-choose'
import { useStreams } from '@/lib/utils'
import useUIMemory from '@/logics/memory'
import services from '@/services'
import type { GroupTag } from '@/services/contact-types/groups'
import './index.module.less'

export default function GroupBindTags(props: {
  groupId: string | null // 要绑定标签的群
  boundTags?: GroupTag[] | null // 此群当前已绑定的标签，若不指定会自动加载
  onFinish: () => void
}) {
  const { groupId, boundTags, onFinish } = props

  return <EditModal
    title="群标签"
    width="650px"
    styleName="modal"
    open={groupId !== null}
    onCancel={onFinish}
  >
    {groupId !== null ? <Content groupId={groupId} boundTags={boundTags} /> : null}
  </EditModal>
}

function Content(props: { groupId: string; boundTags?: GroupTag[] | null }) {
  const { groupId, boundTags: initialBoundTags } = props

  const [allTags] = useStreams(services.groups.tags)
  const loadAllTags = useCallback(() => {
    void services.groups.loadTags()
  }, [])
  useEffect(() => void loadAllTags(), [loadAllTags])

  const [boundTags, setBoundTags] = useState(initialBoundTags ?? [])
  const [loadingInitial, setLoadingInitial] = useState(initialBoundTags === undefined)
  useEffect(() => {
    if (!initialBoundTags) {
      void services.groups.getBoundTags(groupId).then(res => {
        if (res.success) {
          setBoundTags(res.data)
          setLoadingInitial(false)
        }
      })
    }
  }, [groupId, initialBoundTags])

  const [recentTags, setRecentTags] = useUIMemory<GroupTag[]>('recent-group-tags', [])
  const usableRecentTags = useMemo(() => {
    return recentTags
      .filter(tag => allTags.find(t => t.id === tag.id))
      .filter(tag => !boundTags.find(t => t.id === tag.id))
  }, [recentTags, allTags, boundTags])

  const bind = useCallback(
    async (tag: GroupTag) => {
      setBoundTags([...boundTags, tag])
      setRecentTags([tag, ...recentTags.filter(t => t.id !== tag.id).slice(0, 10)])

      const res = await services.groups.bindTag(groupId, tag.id)
      if (!res.success) {
        void message.warning(`操作失败：${res.error}`)
        setBoundTags(boundTags)
      }
    },
    [groupId, boundTags, recentTags, setRecentTags],
  )

  const unbind = useCallback(
    async (id: number) => {
      setBoundTags(boundTags.filter(tag => tag.id !== id))

      const res = await services.groups.unbindTag(groupId, id)
      if (!res.success) {
        void message.warning(`操作失败：${res.error}`)
        setBoundTags(boundTags)
      }
    },
    [groupId, boundTags],
  )

  const [adding, setAdding] = useState(false)
  const addFinish = useCallback(
    (tag?: GroupTag) => {
      if (tag) void bind(tag)
      setAdding(false)
    },
    [bind],
  )

  const [search, setSearch] = useState('')
  const onSearchSelect = useCallback(
    (value: string) => {
      const tag = allTags.find(t => t.name === value)
      if (tag) {
        setSearch('')
        void bind(tag)
      }
    },
    [allTags, bind],
  )

  const filterOption = useCallback((inputValue: string, option?: DefaultOptionType) => {
    return !!option && keywordCompare(inputValue.trim(), option.value as string)
  }, [])
  const options = useMemo(() => {
    return allTags.map(tag => {
      const bound = !!boundTags.find(t => t.id === tag.id)
      return {
        value: tag.name,
        label: `${tag.name}${bound ? '（已绑定）' : ''}`,
        disabled: bound,
      }
    })
  }, [allTags, boundTags])

  return <>
    <header>
      <div styleName="add">
        <Button
          type="primary"
          icon={<PlusOutlined />}
          disabled={loadingInitial}
          onClick={() => setAdding(true)}
        >
          新建标签
        </Button>
      </div>
      <AddOrChooseTagModal
        adding={adding}
        choosable={true}
        choosed={boundTags}
        initialInput={search}
        onFinish={addFinish}
      />

      <AutoComplete
        disabled={loadingInitial}
        filterOption={filterOption}
        options={options}
        value={search}
        onChange={setSearch}
        onSelect={onSearchSelect}
      >
        <Input suffix={<SearchOutlined />} placeholder="搜索选择标签" />
      </AutoComplete>

      {usableRecentTags.length ? (
        <div styleName="recent">
          <label>常用标签</label>
          <div>
            {usableRecentTags.map(tag => <Tag key={tag.id} onClick={async () => bind(tag)}>
              {tag.name}
            </Tag>)}
          </div>
        </div>
      ) : null}
    </header>

    <main>
      <h3>已绑定标签</h3>

      {boundTags.map(tag => <Tag
        key={tag.id}
        closable
        onClose={e => {
          e.preventDefault()
          void unbind(tag.id)
        }}
      >
        {tag.name}
      </Tag>)}

      {loadingInitial ? <Spin /> : null}
      {!loadingInitial && !boundTags.length ? <div styleName="empty">尚未绑定标签</div> : null}
    </main>
  </>
}
